package com.tools.cleanmaster.ui.view.trash;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.hm.base.android.ui.view.CommonInfoView;
import com.nineoldandroids.animation.Animator;
import com.nineoldandroids.animation.AnimatorListenerAdapter;
import com.nineoldandroids.animation.AnimatorSet;
import com.nineoldandroids.animation.ObjectAnimator;
import com.nineoldandroids.animation.ValueAnimator;
import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener;
import com.nineoldandroids.view.ViewHelper;
import com.tools.cleanmaster.CleanApplication;
import com.tools.cleanmaster.R;
import com.tools.cleanmaster.utils.FeatureConfig;
import com.tools.cleanmaster.utils.LogHelper;
import com.tools.cleanmaster.utils.StringUtils;
import com.tools.cleanmaster.utils.Utils;

public class TrashCleanLayout extends CommonInfoView<CleanApplication> {

    private static final String TAG = "TrashCleanLayout";

    private static final float SCALE_TO_SIZE = 1.0f;
    private static final long UP_ANIM_TIME = 300;

    /**
     * 展示tips的距离阈值，小于则进行展示
     */
    private static final int DISPLAY_TIPS_MARGIN_TOP = Utils.dipToPx(CleanApplication.getInstance(), 24);

    // 保护距离，在偏移在该保护距离内算作点击
    private static final int PROTECT_DISTANCE = Utils.dipToPx(CleanApplication.getInstance(), 5);

    private View mTrashCleanHeaderLayout;
    // 手指滑动时trashCleanView的缩放比例
    private float mScaleSize = SCALE_TO_SIZE;

    private int mTopDistance;
    private int mBottomDistance;
    private int mIntervalDistance;
    private VelocityTracker mVelocityTracker;

    private ListView mExplanListView;
    private RelativeLayout.LayoutParams mExplanListLayoutParams;
    private boolean mIsScrollToTop;

    // 是否扫描完成
    private boolean mIsScanFinished;
    private boolean mIsCleaning;
    // 是否是收缩状态
    private boolean mIsShrink;
    private int mInterceptLastMotionY;
    private int mOnTouchLastMotionY;

    private TextView mSizeTipsTV;

    private Animation mFadeInAnim, mFadeOutAnim;
    private Resources mResources;
    private View mTrashTopView;
    private TextView trashSize;
    private TextView trashUnit;

    public TrashCleanLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mResources = getResources();
        inflate(context, R.layout.trash_clean_layout, this);

        mTopDistance = mResources.getDimensionPixelSize(R.dimen.trash_tips_height);
        mBottomDistance = mResources.getDimensionPixelSize(R.dimen.explansion_margin_top);
        mIntervalDistance = mBottomDistance - mTopDistance;

        mFadeInAnim = AnimationUtils.loadAnimation(context, R.anim.fade_in);
        mFadeOutAnim = AnimationUtils.loadAnimation(context, R.anim.fade_out);

    }

    @SuppressLint("NewApi")
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mTrashCleanHeaderLayout = findViewById(R.id.trash_clean_header_layout);
        mTrashTopView = findViewById(R.id.scan_trash_top_layout);
        mSizeTipsTV = findViewById(R.id.trash_size_tips_tv);
        mExplanListView = findViewById(R.id.list);
        trashSize = findViewById(R.id.trash_size);
        trashUnit = findViewById(R.id.trash_size_unit);
        mExplanListLayoutParams = (RelativeLayout.LayoutParams) mExplanListView.getLayoutParams();
        mExplanListView.setVerticalFadingEdgeEnabled(true);
        mExplanListView.setFadingEdgeLength((int) getResources().getDimension(R.dimen.list_fading_edge));

        if (Build.VERSION.SDK_INT > 8) {
            mExplanListView.setOverScrollMode(View.OVER_SCROLL_NEVER);
        }

        mExplanListView.setOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if (firstVisibleItem == 0) {
                    //first item complete visible
                    View first = mExplanListView.getChildAt(0);
                    if (first != null && first.getTop() == 0) {
                        mIsScrollToTop = true;
                    }
                } else {
                    mIsScrollToTop = false;
                }
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (mIsScanFinished && !mIsCleaning) {
            int y = (int) ev.getY();
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mInterceptLastMotionY = y;
                    break;
                case MotionEvent.ACTION_MOVE:
                    int dy = y - mInterceptLastMotionY;
                    dy = fixLastMotionY(ev, dy);
                    if (haveListVisible() && (Math.abs(dy) >= PROTECT_DISTANCE) && (
                            (mIsShrink && dy > 0 && mIsScrollToTop) || (!mIsShrink && dy < 0))) {
                        return true;
                    }
                    break;
                default:
                    break;
            }
        }
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int y = (int) event.getY();
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mOnTouchLastMotionY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                int dy = y - mOnTouchLastMotionY;
                dy = fixLastMotionY(event, dy);
                if (mExplanListView.getVisibility() == View.VISIBLE) {
                    doAnimByMove(mExplanListView, mExplanListLayoutParams, dy);
                }
                mOnTouchLastMotionY = y;
                break;
            case MotionEvent.ACTION_UP:

                handleUpAnim(mExplanListLayoutParams.topMargin);
                releaseVelocityTracker();
                break;

            case MotionEvent.ACTION_CANCEL:
                releaseVelocityTracker();
                break;

        }

        return super.onTouchEvent(event);
    }

    private int fixLastMotionY(MotionEvent event, int dy) {
        if (!mIsShrink && dy > 0) {//非收缩状态往下移动
            mOnTouchLastMotionY = (int) event.getY();
            mInterceptLastMotionY = (int) event.getY();
            dy = 0;
        }
        return dy;
    }

    @Override
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        super.requestDisallowInterceptTouchEvent(false);
    }

    /**
     * 根据当时手指移动的距离对大圈做缩放，将view往上移动
     *
     * @param view 对应的向上移动view
     * @param lp   LayoutParams
     * @param dy   滑动的距离
     */
    private void doAnimByMove(View view, RelativeLayout.LayoutParams lp, int dy) {
        if (dy != 0) {
            int topMargin = mExplanListLayoutParams.topMargin;
            topMargin += dy;
            if (topMargin <= mTopDistance) {
                topMargin = mTopDistance;
            }
            if (topMargin >= mBottomDistance) {
                topMargin = mBottomDistance;
            }
            lp.topMargin = topMargin;
            doScaleByTopMargin(topMargin);
            view.setLayoutParams(lp);
            handleTipsDisplay(lp, false);
        }
    }

    /**
     * 用于处理垃圾tip的显示与隐藏
     *
     * @param lp          list layoutParams
     * @param isDisappear 是否强制控制隐藏
     */
    public void handleTipsDisplay(RelativeLayout.LayoutParams lp, boolean isDisappear) {

        if (isDisappear) {
            if (mSizeTipsTV.getVisibility() == View.VISIBLE) {
                mTrashTopView.setVisibility(View.VISIBLE);
                mSizeTipsTV.setVisibility(View.INVISIBLE);
                mSizeTipsTV.startAnimation(mFadeOutAnim);
            }
            return;
        }
        if (lp == null) {
            return;
        }

        if (lp.topMargin <= Utils.dipToPx(CleanApplication.getInstance(), DISPLAY_TIPS_MARGIN_TOP)) {
            if (mSizeTipsTV.getVisibility() == View.INVISIBLE) {
                mTrashTopView.setVisibility(View.INVISIBLE);
                mSizeTipsTV.setVisibility(View.VISIBLE);
                mSizeTipsTV.startAnimation(mFadeInAnim);
            }
        } else {
            if (mSizeTipsTV.getVisibility() == View.VISIBLE) {
                mTrashTopView.setVisibility(View.VISIBLE);
                mSizeTipsTV.setVisibility(View.INVISIBLE);
                mSizeTipsTV.startAnimation(mFadeOutAnim);
            }
        }
    }

    /**
     * 根据listview 距离顶部的距离计算缩放比例
     */
    private void doScaleByTopMargin(int topMargin) {
        if (FeatureConfig.DEBUG_LOG) {
            LogHelper.d(TAG, "topMargin = " + topMargin);
        }
        resetScaleSize(topMargin);
        resetIsShrink();
        if (0 <= mScaleSize && mScaleSize <= SCALE_TO_SIZE) {
            ViewHelper.setPivotX(mTrashCleanHeaderLayout, mTrashCleanHeaderLayout.getWidth() / 2);
            ViewHelper.setPivotY(mTrashCleanHeaderLayout, 0);
            ViewHelper.setScaleX(mTrashCleanHeaderLayout, mScaleSize);
            ViewHelper.setScaleY(mTrashCleanHeaderLayout, mScaleSize);
        }
        if (FeatureConfig.DEBUG_LOG) {
            LogHelper.d(TAG, "topMargin = " + topMargin + "----scaleSize = " + mScaleSize);
        }
    }

    /**
     * 根据up时的状态将TrashCleanView和ListView动画到对应状态
     */
    public void handleUpAnim(int topMargin) {
        float scaleSize = resetScaleSize(topMargin);
        resetIsShrink();

        ValueAnimator listAnimator;
        ObjectAnimator trashXAnimator;
        ObjectAnimator trashYAnimator;
        AnimatorSet animatorSet;

        ViewHelper.setPivotX(mTrashCleanHeaderLayout, mTrashCleanHeaderLayout.getWidth() / 2);
        ViewHelper.setPivotY(mTrashCleanHeaderLayout, 0);
        if (scaleSize < SCALE_TO_SIZE / 2) {
            mScaleSize = 0;
            resetIsShrink();
            // 将圆环缩放为0,将listview向上移
            listAnimator = ValueAnimator.ofFloat(mExplanListLayoutParams.topMargin, mTopDistance);
            listAnimator.setDuration(UP_ANIM_TIME);

            trashXAnimator = ObjectAnimator.ofFloat(mTrashCleanHeaderLayout, "scaleX", scaleSize, 0);
            trashXAnimator.setDuration(UP_ANIM_TIME);
            trashYAnimator = ObjectAnimator.ofFloat(mTrashCleanHeaderLayout, "scaleY", scaleSize, 0);
            trashYAnimator.setDuration(UP_ANIM_TIME);
        } else {
            mScaleSize = SCALE_TO_SIZE;
            resetIsShrink();
            // 将圆环放大,将listview向下移
            listAnimator = ValueAnimator.ofFloat(mExplanListLayoutParams.topMargin, mBottomDistance);
            listAnimator.setDuration(UP_ANIM_TIME);
            trashXAnimator = ObjectAnimator.ofFloat(mTrashCleanHeaderLayout, "scaleX", scaleSize, SCALE_TO_SIZE);
            trashXAnimator.setDuration(UP_ANIM_TIME);
            trashYAnimator = ObjectAnimator.ofFloat(mTrashCleanHeaderLayout, "scaleY", scaleSize, SCALE_TO_SIZE);
            trashYAnimator.setDuration(UP_ANIM_TIME);
        }

        listAnimator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animator) {
                float animatedValue = (Float) animator.getAnimatedValue();
                mExplanListLayoutParams.topMargin = (int) animatedValue;
                mExplanListView.setLayoutParams(mExplanListLayoutParams);
            }
        });

        listAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                handleTipsDisplay(mExplanListLayoutParams, false);
            }
        });

        animatorSet = new AnimatorSet();
        animatorSet.playTogether(listAnimator, trashXAnimator, trashYAnimator);
        animatorSet.start();
    }

    private void releaseVelocityTracker() {
        if (null != mVelocityTracker) {
            mVelocityTracker.clear();
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }

    }

    private boolean haveListVisible() {
        return mExplanListView.getVisibility() == View.VISIBLE;
    }

    private void resetIsShrink() {
        if (mScaleSize == 0) {
            mIsShrink = true;
        } else if (mScaleSize == SCALE_TO_SIZE) {
            mIsShrink = false;
        }
    }

    private float resetScaleSize(int topMargin) {
        mScaleSize = (topMargin - mTopDistance) / (mIntervalDistance / SCALE_TO_SIZE);
        if (mScaleSize <= 0) {
            mScaleSize = 0;
        } else if (mScaleSize >= SCALE_TO_SIZE) {
            mScaleSize = SCALE_TO_SIZE;
        }
        return mScaleSize;
    }

    public void setIsCleaning(boolean isCleaning) {
        mIsCleaning = isCleaning;
    }

    /**
     * 设置是否扫描结束
     */
    public void setIsScanFinished(boolean isFinished) {
        mIsScanFinished = isFinished;
    }

    /**
     * 获取TrashCleanView是否是收缩状态
     *
     * @return true Shrink,scaleSize = 0; false stretch,scale size =
     * SCALE_TO_SIZE
     */
    public boolean isCircleShrink() {
        return mIsShrink;
    }

    /**
     * 设置是否是收缩状态
     */
    public void setIsShrink(boolean isShrink) {
        mIsShrink = isShrink;
    }

    /**
     * 设置收缩状态下的tip文案是否展示
     */
    public void setTrashSize(long size) {
        String[] sizeUnitString = StringUtils.getSizeUnitString(size);
        mSizeTipsTV.setText(getContext().getString(R.string.trash_clean_size_tips,
                StringUtils.getSizeString(size)));
        trashSize.setText(sizeUnitString[0]);
        trashUnit.setText(sizeUnitString[1]);
    }

    /**
     * 重置扫面到扫面结束状态
     */
    public void resetScanFinshState() {
        mSizeTipsTV.setVisibility(INVISIBLE);
        mSizeTipsTV.clearAnimation();
        mIsShrink = false;
        handleUpAnim(mExplanListLayoutParams.topMargin);
    }
}
